package com.dpiinc.TechPage.viewmodel

import android.app.Application
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import com.dpiinc.TechPage.AIWriteApplication
import com.dpiinc.TechPage.AWLog
import com.dpiinc.TechPage.R
import com.dpiinc.TechPage.api.EditNoteApi
import com.dpiinc.TechPage.constants.FileType
import com.dpiinc.TechPage.model.FileBean
import com.dpiinc.TechPage.oss.DownloadTask
import com.dpiinc.TechPage.oss.FileDownloadHelper
import com.dpiinc.TechPage.oss.UploadTask
import com.dpiinc.TechPage.repository.EditNoteRepository
import com.dpiinc.TechPage.repository.NetworkState
import com.dpiinc.TechPage.repository.Status
import com.dpiinc.TechPage.room.RoomAiWriterDatabase
import com.dpiinc.TechPage.room.bean.NoteEntity
import com.dpiinc.TechPage.utils.AudioRecordHelper
import com.dpiinc.TechPage.utils.DateUtils
import com.beiji.lib.pen.cache.PenCacheManager
import com.czt.mp3recorder.Mp3Recorder
import java.io.File

/**
 * 新建笔记、编辑笔记 ViewModel
 * Created by X on 2018/7/7.
 */
class EditNoteViewModel(val note: NoteEntity, application: Application) : AndroidViewModel(application) {

    companion object {
        fun generateNoteId(): String {
            return "_" + DateUtils.getCurrentTimeMillis().toString()
        }

        fun generateNoteName(): String {
            val formatString = AIWriteApplication.instance().resources.getString(R.string.edit_note_title_time)
            val dateString = DateUtils.getDateString(DateUtils.getCurrentTimeMillis(), formatString)
            return "$dateString " + AIWriteApplication.instance().resources.getString(R.string.edit_note_title)
        }

        private const val TAG = "EditNoteViewModel"
    }

    var hasEdited: Boolean = false
    var hasNewStrokes: Boolean = false
    var needRedraw: Boolean = false
    var needRecognize: Boolean = false

    private val repository = EditNoteRepository(RoomAiWriterDatabase.getInstance(application), EditNoteApi.create())

    private val operationTrigger = MutableLiveData<Int>()
    private val apiResult = Transformations.map(operationTrigger) {
        repository.doOperation(operationTrigger.value!!, note)
    }

    val networkState: LiveData<NetworkState> = Transformations.switchMap(apiResult) { it }

    val downloadState = MutableLiveData<NetworkState>()

    init {
        if (note.createTime == 0L) {
            note.createTime = DateUtils.getCurrentTimeMillis()
            note.modifyTime = DateUtils.getCurrentTimeMillis()
        }
    }

    fun saveToLocal() {
        if (note.noteName.isNullOrEmpty()) {
            note.noteName = generateNoteName()
        }
        note.modifyTime = DateUtils.getCurrentTimeMillis()
        repository.saveToLocal(note)
    }

    fun saveToServer(): Boolean {
        if (hasEdited) {
            saveToLocal()
            operationTrigger.value = EditNoteRepository.OPERATION_SAVE
            return true
        }
        return false
    }

    fun delete() {
        operationTrigger.value = EditNoteRepository.OPERATION_DELETE
    }

    fun clear() {
        operationTrigger.value = EditNoteRepository.OPERATION_CLEAR
    }


    fun startRecordAudio(onAudioRecordingCallback: Mp3Recorder.Callback): File? {
        val audioFile = PenCacheManager.instance.getCurrentCache()?.newAudioFile() ?: return null
        try {
            AudioRecordHelper.startRecord(audioFile, onAudioRecordingCallback)
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
        return audioFile
    }

    fun endRecordAudio(): File? {
        val audioFile = AudioRecordHelper.endRecord() ?: return null
        val audioFiles = (note.recordFiles ?: ArrayList()) as ArrayList
        audioFiles.add(FileBean().apply {
            name = audioFile.name
            fileUrl = audioFile.path
            modifyTime = DateUtils.getCurrentTimeMillis()
            isNew = true
        })
        val uploadTask = UploadTask(note.noteId, FileType.AUDIO_FILE, audioFiles.size - 1).apply {
            fileName = audioFile.name
            filePath = audioFile.path
            //TODO 录音开始时间？
            time = DateUtils.getCurrentTimeMillis()
        }
        RoomAiWriterDatabase.getInstance(getApplication()).uploadTaskDao().insert(uploadTask)
        return audioFile
    }

    fun targetDotFileIsExist(): Boolean {
        val cacheFolder = PenCacheManager.instance.getCacheFolder(note.noteId)
        if (note.dotFiles == null) {
            needRedraw = false
            return needRedraw
        }
        val targetFilePath = File(cacheFolder, note.dotFiles!!.name)
        needRedraw = targetFilePath.exists()
        return needRedraw
    }

    fun downloadFilesIfNotExists(): Boolean {
        val downloadTaskList = ArrayList<DownloadTask>()
        val cacheFolder = PenCacheManager.instance.getCacheFolder(note.noteId)
        if (cacheFolder == null) {
            Log.i(TAG, "downloadFilesIfNotExists: cacheFolder == null")
        } else {
            Log.i(TAG, "downloadFilesIfNotExists: cacheFolder != null")
        }
        if (!cacheFolder.exists()) {
            cacheFolder.mkdir()
        }
        if (cacheFolder.listFiles()?.filter { it.name.endsWith("png") && it.name.split("-").size == 4 }
                ?.isNotEmpty() == true) {
            needRedraw = true
            cacheFolder.listFiles()?.filter { it.name.endsWith("png") }?.forEach {
                it.delete()
            }
        }
//   if (cacheFolder.listFiles()?.filter { it.name.endsWith("png") && it.name.split("-").size == 4 }
//                ?.isNotEmpty() == true) {
        note.dotFiles?.let { file ->
            val targetFilePath = File(cacheFolder, file.name)
            if (!targetFilePath.exists()) {
                needRedraw = true
                downloadTaskList.add(DownloadTask(file.fileUrl, targetFilePath.path))
            }
        }
        note.recordFiles?.forEach { file ->
            val targetFilePath = File(cacheFolder, file.name)
            if (!targetFilePath.exists()) {
                downloadTaskList.add(DownloadTask(file.fileUrl, targetFilePath.path))
            }
        }
        if (downloadTaskList.isEmpty()) {
            downloadState.postValue(NetworkState(Status.SUCCESS))
            return false
        }
        //TODO
        downloadState.value = NetworkState(Status.RUNNING, AIWriteApplication.instance().resources.getString(R.string.edit_note_loading))
//        OssFileManager.instance.asyncGetFiles(downloadTaskList) { resultData, progress, isComplete ->
//            AWLog.e("download", "$progress.........$resultData")
//            downloadState.postValue(NetworkState(Status.RUNNING, progress.toString()))
//            if (isComplete) {
//                if (progress == 1f) {
//                    AWLog.i("download", "download complete.")
//                    downloadState.postValue(NetworkState(Status.SUCCESS))
//                } else {
//                    AWLog.e("download", "download failed.")
//                    downloadState.postValue(NetworkState(Status.FAILED))
//                }
//            }
//        }
        FileDownloadHelper.downloadFiles(downloadTaskList) { resultData, progress, isComplete ->
            AWLog.e("download", "$progress.........$resultData")
            val progressString = "${(progress * 100).toInt()}%"
            downloadState.postValue(NetworkState(Status.RUNNING, progressString))
            if (isComplete) {
                if (progress == 1f) {
                    AWLog.i("download", "download complete.")
                    downloadState.postValue(NetworkState(Status.SUCCESS))
                } else {
                    AWLog.e("download", "download failed.")
                    downloadState.postValue(NetworkState(Status.FAILED))
                }
            }
        }
        return true
    }

    fun addUpload(uploadTask: UploadTask) {
        repository.insertUploadTask(uploadTask)
    }


}